CloudflareがCDN向けキャッシュヘッダーCDN-Cache-Controlを実装したので触ってみた
昨年から特定用途に特化したキャッシュを制御するHTTPレスポンスヘッダーの仕様がAkamai/Cloudflare/Fastlyから共同提案されています。
- Targeted HTTP Response Header Fields for Cache Control
- CDNのキャッシュを制御する CDN-Cache-Control ヘッダ - ASnoKaze blog
共著者の一社であるCloudflareがCDN向けのCDN-Cache-Controlを早速正式リリースしたため、触ってみました。
CDN-Cache-Control はどういうキャッシュ?
Webコンテンツの配信を最適化するために、HTTPレスポンスヘッダーを利用したキャッシュ機能がよく使われ、 プロキシサーバー、CDN、ブラウザなど様々なコンポーネントで可能です。
例えば
Cache-Control: max-age=60, s-maxage=120
というレスポンスを返すと、ブラウザでは60秒キャッシュされ、プロキシ、CDN 向けでは 120 秒キャッシュされます。
とはいえ、より細かい粒度でキャッシュ設定したいことがあります。
その要望に答えるのが本提案であり、キャッシュの用途別のレスポンスヘッダーを定義しています。 その第1段が CDNキャッシュに特化した CDN-Cache-Control フィールドです。
This specification defines a convention for HTTP response header fields that allow directives controlling caching to be targeted at specific caches or classes of caches. It also defines one such header field, targeted at Content Delivery Network (CDN) caches.
https://www.ietf.org/archive/id/draft-cdn-control-header-01.html#name-cache-behavior
Cloudflare は他社に先駆けて、この機能をリリースしました。
CDN-Cache-Control を使うと、
- プロキシとCDNでキャッシュ設定を分ける
- 多段CDN構成でCDN全体で一貫した同じキャッシュ設定を用いる
- 多段CDN構成でデフォルトのキャッシュ設定を定義しつつ、特定のCDNだけ別設定を定義
- マルチCDN構成でCDNキャッシュ設定をオリジンに寄せる
といったことが可能になります。
この動作を確認します。
キャッシュの優先準備
CDNのキャッシュ設定は様々な方法があります。
優先順位は高いものから順に以下の通りです。
- (CDN側)Edge Cache TTL Page Rule
- (オリジン側)Cloudflare-CDN-Cache-Control ※ Cloudflare CDN固有のキャッシュ設定
- (オリジン側)CDN-Cache-Control ※ CDN汎用のキャッシュ設定
- (オリジン側)Cache-Control:s-max-age
- (CDN側)Cloudflare デフォルト
プロキシとCDNでキャッシュ設定を分ける
一番基本的な使い方です。
Cache-Controlのs-maxageの設定は、共有キャッシュ全体で適用されます。
共有キャッシュをCDN系とその他(プロキシ)で分けたい場合、次の通り設定します。
Cache-Control: max-age=60, s-maxage=120 CDN-Cache-Control: max-age=600
リクエストします。
HTTP/1.1 200 OK Date: Sun, 23 May 2021 22:38:14 GMT Content-Type: image/png Content-Length: 368 Connection: keep-alive Last-Modified: Sat, 22 May 2021 11:53:42 GMT ETag: "60a8f0c6-170" Cache-Control: max-age=60, s-maxage=120 CDN-Cache-Control: max-age=600 CF-Cache-Status: MISS Accept-Ranges: bytes cf-request-id: 0a3cfa10cd0000416ee095a000000001 Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=M...M"}],"group":"cf-nel","max_age":604800} NEL: {"report_to":"cf-nel","max_age":604800} Server: cloudflare CF-RAY: 6541c5faeb7a416e-HAM
CDN がキャッシュ後 CDN-Cache-Control: max-age 内であれば、 CDN キャッシュにヒットします。
... CF-Cache-Status: HIT Age: 82 ...
CDN-Cache-Control: max-age を超えると、オリジンに条件付きリクエストをします。 その時の CF-Cache-Status は REVALIDATED です。
... CF-Cache-Status: REVALIDATED ...
CDN-Cache-Control は以下のディレクティブに対応しています。
- max-age
- must-revalidate
- no-store
- no-cache
- private
多段CDN構成でCDN全体で一貫した同じキャッシュ設定を用いる
オリジンとブラウザの間に複数のCDNを挟む多段CDN構成が採用されることがあります。
そのような構成において、各 CDN のキャッシュ設定を統一させたい場合、CDN-Cache-Control を活用できます。
Cache-Control: max-age=60, s-maxage=120 CDN-Cache-Control: max-age=600
CDN-Cache-Control ヘッダーはダウンストリーム(ブラウザ寄り)にも渡されるので、 ダウンストリームにいる CDN が CDN-Cache-Control をサポートする場合、そのCDNにも同じキャッシュ設定が適用されます。
現時点では CDN-Cache-Control をサポートする CDN は Cloudflare だけのため、将来に期待しましょう。
多段CDN構成でデフォルトのキャッシュ設定を定義しつつ、特定のCDNだけ別設定を定義
オリジンとブラウザの間に複数のCDNを挟む多段CDN構成が採用されることがあります。
そのような構成において、CDN全体でデフォルトのキャッシュ設定を定義しつつ、特定のCDNだけキャッシュ設定を分けたい場合、CDN-Cache-Control を Cloudflare-CDN-Cache-Controlと組み合わせて活用します。
Cloudflare-CDN-Cache-Control は Cloudflare CDN に特化したキャッシュ用レスポンスフィールドです。
Cache-Control: max-age=60, s-maxage=120 CDN-Cache-Control: max-age=600 Cloudflare-CDN-Cache-Control: max-age=180
Cloudflare CDNでは Cloudflare-Cache-Control は s-max-age や CDN-Cache-Control よりも優先して評価されます。 また、Cloudflare-CDN-Cache-Control ヘッダーは Cloudflare CDNでしか処理されないため、Cloudflare CDNのダウンストリームにはこのヘッダーを返しません。
HTTP/1.1 200 OK ... Cache-Control: max-age=60, s-maxage=120 CDN-Cache-Control: max-age=600 CF-Cache-Status: MISS ...
なお、CDN 汎用的なヘッダー CDN-Cache-ControlとCDNベンダー固有のヘッダー(上記例では Cloudflare-CDN-Cache-Control)間では、先頭のものほど優先される target list として管理されます。
[ExampleCDN-Cache-Control, CDN-Cache-Control]
このリストは、実装により、固定、ユーザーがカスタマイズ可能、あるいはリクエストごとにカスタマイズ可能となるようです。
2.1. Cache Behavior
A cache that implement this specification has a target list - an ordered list of the targeted field names that it uses for caching policy, with the order reflecting priority from most applicable to least. The target list might be fixed, user-configurable, or generated per request, depending upon the implementation.
https://www.ietf.org/archive/id/draft-cdn-control-header-01.html#name-cache-behavior
マルチCDN構成でCDNキャッシュ設定をオリジンに寄せる
エリアや CDN のサービス稼働状況によって CDN を使い分ける マルチ CDN 構成が採用されることがあります。
そのような構成において、CDN のキャッシュ保持期間設定をオリジンサーバーで一元管理したい場合、CDN-Cache-Control を活用できます。
Cloudflare Edge Cache TTL Page Rule は最優先される
Cloudflare ではオリジンのキャッシュヘッダーとは別に、Cloudflare CDN の設定画面でエッジの TTL を設定できます。
ルールが存在する場合、Cloudflare-CDN-Cache-Control/CDN-Cache-Control よりも優先されます。
Edge Cache TTL Page Rule で2時間キャッシュするよう設定します。
この状態でのレスポンスの抜粋です。
... Cache-Control: max-age=60, s-maxage=120 CDN-Cache-Control: max-age=600 CF-Cache-Status: HIT Age: 3120 ...
エッジキャッシュは CDN-Cache-Controlのmax-age=600よりも経過しているにも関わらず(Age=3120)、キャッシュ・ヒットしています。
Edge Cache TTL Page Rule の設定が Cloudflare-CDN-Cache-Control/CDN-Cache-Control よりも優先されていることがわかります。
フォールバックは Cloudflare デフォルトの TTL
Cloudflare CDN は HTTP ステータスごとにデフォルトのキャッシュ時間が設定されています。 例えば、200 ステータスは 120分キャッシュされます。
- Cloudflare-CDN-Cache-Control
- CDN-Cache-Control
- Cache-Control(s-max-age)
いずれも存在しない場合、このデフォルト TTL が適用されます。
最後に
CDNキャッシュ向けのHTTPレスポンスヘッダー CDN-Cache-Controlの仕様がAkamai・Cloudflare・Fastlyの3社から提案されており、 Cloudflare が提案中の仕様を早速サービス提供しました。
本機能を使うと
- 共有キャッシュの設定をCDNとその他で分ける
- 複数のCDNのキャッシュ設定を一元管理する
といったことを、オリジンのレスポンスヘッダーで柔軟に制御できます。
Cloudflareと共同で本仕様を提案している Akamai・Fastly からも本機能が順次リリースされると思われ、サポートするCDNサービスが他にも増えるにつれて、本ヘッダーの魅力も増しそうです。
様々なCDNを飼い慣らしたい人には、大注目の仕様です。
更新
RFC 化
本エントリで紹介している"Targeted HTTP Response Header Fields for Cache Control" は RFC 9213: Targeted HTTP Cache Control として2022年6月に公開されました。
Akamai 対応
2021年6月に Akamai からも CDN-Cache-Control
対応が発表されました。
Akamai Blog | Targeted Cache Control
Akamai の場合、20年以上前から対応していた Edge-Control
の標準化です。